import { useCallback, useState, useRef } from "react";
import useMountedState from "./useMountedState";

export default function useAsyncFn(fn) {
  const lastCallId = useRef(0);
  const [state, set] = useState<any>({ loading: false });
  const isMounted = useMountedState();
  const handleFn = useCallback(
    (...args) => {
      const callId = ++lastCallId.current;
      set({ loading: true });
      return fn(...args).then(
        value => {
          const callback = args[args.length - 1];
          if (isMounted() && callId === lastCallId.current) {
            if (typeof callback === "function") {
              callback();
            }
            set({ value, loading: false });
          }
          return value;
        },
        error => {
          if (isMounted() && callId === lastCallId.current) {
            set({ error, loading: false });
          }
          return null;
        }
      );
    },
    [fn]
  );

  return [state, handleFn];
}
